不知不覺介紹了 8 種特別的 DuckDB SQL,今天是第九天,所以來介紹一個跟咒術迴戰一樣特別經離叛道的 DuckDB SQL
首先我們先來創建一個咒術迴戰的 table
CREATE TABLE sorcery_battle(id, names) AS
VALUES
(1, ARRAY['Gojo Satoru', 'Itadori Yuji', 'Fushiguro Megumi', 'Kugisaki Nobara']),
(2, ARRAY['Sukuna', 'Nanami Kento', 'Todo Aoi']),
(3, ARRAY['Maki Zenin', 'Inumaki Toge'])
接著把名子裡面有 'to' 的挑出來,因為感覺他們
SELECT
id,
array_agg(name ORDER BY name) AS filtered_names
FROM (
SELECT
id,
unnest(names) AS name
FROM sorcery_battle
) AS unpacked
WHERE name ILIKE '%to%'
GROUP BY id
ORDER BY id;
id filtered_names
1 [Gojo Satoru]
2 [Nanami Kento, Todo Aoi]
3 [Inumaki Toge]
就像在第八天說的,DuckDB 吸收了很多 Dataframe 的優點,除此之外 DuckDB 也從 Python 身上借鏡了不少語法。
比方說,上面的 Postgres SQL 需要 unnest 一次再重組每個 names array,
但是在python 中要 filter 每個 list 好做非常多。
import pandas as pd
df = pd.DataFrame({
'id': [1, 2, 3],
'names': [
['Gojo Satoru', 'Itadori Yuji', 'Fushiguro Megumi', 'Kugisaki Nobara'],
['Sukuna', 'Nanami Kento', 'Todo Aoi'],
['Maki Zenin', 'Inumaki Toge']
]
})
def filter_names(name_list):
return [name for name in name_list if 'to' in name.lower()]
df['filtered_names'] = df['names'].apply(filter_names)
print(df)
這其中的關鍵,就在於
相信你可以猜到, DuckDB 可以支援 list comprehension 😎
SELECT
id,
names,
[name FOR name IN names IF name.lower().contains('to')] AS filtered_names
FROM (
VALUES
(1, ['Gojo Satoru', 'Itadori Yuji', 'Fushiguro Megumi', 'Kugisaki Nobara']),
(2, ['Sukuna', 'Nanami Kento', 'Todo Aoi']),
(3, ['Maki Zenin', 'Inumaki Toge'])
) AS sorcery_battle(id, names);
很神奇吧,我第一次看到也是 O口O
趕快到 DuckDB WASM 或 Colab 試試看吧!